namespace FIREFLYX {
    export class OBJMeshProcessor implements IAssetProcessor {
        public Type: AssetType = AssetType.OBJ_MESH;
        public rawType: XMLHttpRequestResponseType = "text";
        public suffix: string = ".obj";
        public parse(data: string): Asset {
            let text = data;
            //构建mesh
            let mData = new MeshData();
            let poss: number[] = [];
            let uvs: number[] = [];
            let normals: number[] = [];
            let triindexs: number[] = [];
            let mesh = new Mesh();
            mesh.data = mData;
            //逐行读取 文本
            let vn: number[] = [];
            let vt: number[] = [];
            let f: string[] = [];
            //fun 1
            let i = 0;
            let _t = text.replace("\r", "\n");
            let lines = _t.split("\n");
            while (i < lines.length) {
                let str = lines[i];
                i++;
                if (str.length < 1 || str[0] == "#") continue;
                let vals = str.split(" ");
                let vArr: string[] = [];
                vals.forEach((s) => { if (s.length > 0) vArr.push(s); });
                if (vArr.length < 1) continue;
                switch (vArr[0]) {
                    case "o": mesh.name = vArr[1] ?? "OBJMesh"; break;
                    case "v":
                        let x = Number(vArr[1]) ?? 0;
                        let y = Number(vArr[2]) ?? 0;
                        let z = Number(vArr[3]) ?? 0;
                        poss.push(x * -1, y, z);
                        break;
                    case "vn": vn.push(Number(vArr[1]) ?? 0, Number(vArr[2]) ?? 0, Number(vArr[3]) ?? 0); break;
                    case "vt": vt.push(Number(vArr[1]) ?? 0, Number(vArr[2]) ?? 0); break;
                    case "f":
                        if (vArr[4] == null) {
                            f.push(vArr[1], vArr[2], vArr[3]);
                        } else {
                            f.push(vArr[1], vArr[2], vArr[4]);
                            f.push(vArr[2], vArr[3], vArr[4]);
                        }
                        break;
                    default:
                }
            }
            //顶点长度确定
            let pointCount = poss.length / 3;
            uvs.length = pointCount * 2;
            normals.length = pointCount * 3;

            let initVMap: { [vIndex: number]: boolean } = {};
            //整理填充meshdata
            for (let j = 0, len = f.length; j < len; j++) {
                let fArr = f[j].split("/");
                let vi = Number(fArr[0]) - 1;
                if (!initVMap[vi]) {
                    initVMap[vi] = true;
                    let ti = 2 * vi;
                    let ni = 3 * vi;
                    let _ti = 2 * (Number(fArr[1]) - 1);
                    let _ni = 3 * (Number(fArr[2]) - 1);

                    uvs[ti] = vt[_ti];
                    uvs[ti + 1] = vt[_ti + 1];

                    normals[ni] = vn[_ni];
                    normals[ni + 1] = vn[_ni + 1];
                    normals[ni + 2] = vn[_ni + 2];
                }
                triindexs.push(vi);
            }
            //
            mData.posArr = new Float32Array(poss);
            mData.uvArr = new Float32Array(uvs);
            mData.normalArr = new Float32Array(normals);
            let burClass = MeshData.GetTriIndexBufferTypeByPosLen(poss.length / 3);
            mData.triIndexArr = new burClass(triindexs);

            mData.calcPosBoundary();
            if (mData.triIndexArr.length > 0) {
                mesh.apply();
            }
            return mesh;
        }
    }
}